-- ********************************************
-- * Copyright (c) 2012 TPV R&D Center Brazil *
-- * All Rights Reserved                      *
-- ********************************************

--- toolkit.component.StackWindow

local StackWindow = {}

local function hasIntersection(rect1, rect2)
   local fIntersect = not (rect2.area.left > (rect1.area.left + rect1.area.width)
                           or (rect2.area.left + rect2.area.width) < rect1.area.left
                           or rect2.area.top > (rect1.area.top + rect1.area.height)
                           or (rect1.area.top + rect2.area.height) < rect1.area.top)
   if (fIntersect) then
      local top = math.max(rect1.area.top, rect2.area.top)
      local left = math.max(rect1.area.left, rect2.area.left)
      local right = math.min((rect1.area.left + rect1.area.width), (rect2.area.left + rect2.area.width))
      local bottom = math.min((rect1.area.top + rect1.area.height), (rect2.area.top + rect2.area.height))
      local width = right - left
      local height = bottom - top

      return {top = top, left = left, width = width, height = height}
   else
      return {}
   end
end

function StackWindow:new(o)
   local newStackWindow = {
      parent = nil,
      stack = {}
   }

   --generate an object
   setmetatable(newStackWindow, self)
   self.__index = self

   return newStackWindow
end

function StackWindow:push(...)
   for _, v in ipairs{...} do
      v.parent = self

      local clipX, clipY, clipW, clipH = canvas:attrClip()
      canvas:attrClip(v.area.left, v.area.top, v.area.width, v.area.height)
      canvas:compose(v.area.left, v.area.top, v.content)
      canvas:attrClip(clipX, clipY, clipW, clipH)

      local intersectList = {}
      for i = 1, #self.stack do
         local w = self.stack[i].window
         local interRect = hasIntersection(v, w)
         table.insert(intersectList, interRect)
      end

      self.stack[#self.stack + 1] = {window = v, intersections = intersectList}
   end

   canvas:flush()
end

function StackWindow:update(tArea, bNeedFlush)
   if (type(tArea) ~= 'table') then
      tArea = {left = 0, top = 0, width = 1280, height = 720}
   end

   local clipX, clipY, clipW, clipH = canvas:attrClip()
   canvas:attrClip(tArea.left, tArea.top, tArea.width, tArea.height)

   --clear
   canvas:attrColor(0, 0, 0, 0)
   canvas:clear()

   for i = 1, #self.stack do
      canvas:compose(self.stack[i].window.area.left, self.stack[i].window.area.top, self.stack[i].window.content)
   end

   if(bNeedFlush) then
      canvas:flush()
   end

   canvas:attrClip(clipX, clipY, clipW, clipH)
end

function StackWindow:pop(num, bAvoidFlush)
   local num = num or 1

   if (num > #self.stack) then
      do return end
   end

   local ret = {}
   for i  = num, 1, -1 do
      local w = table.remove(self.stack)
      ret[#ret + 1] = w

      local clipX, clipY, clipW, clipH = canvas:attrClip()
      canvas:attrClip(w.window.area.left, w.window.area.top, w.window.area.width, w.window.area.height)
      canvas:attrColor(0, 0, 0, 0)
      canvas:clear()

      for i = 1, #w.intersections do
         local intersec = w.intersections[i]
         if (next(intersec)) then
            canvas:compose(self.stack[i].window.area.left, self.stack[i].window.area.top, self.stack[i].window.content)
         end
      end
      canvas:attrClip(clipX, clipY, clipW, clipH)
      w.window = nil
   end

   if (not bAvoidFlush) then
      canvas:flush()
   end
   collectgarbage()

   --return unpack(ret)
end

function StackWindow:replace(window)
   if (#self.stack < 1) then
      self:push(window)
      do return end
   end

   local w = table.remove(self.stack)

   local clipX, clipY, clipW, clipH = canvas:attrClip()
   canvas:attrClip(w.window.area.left, w.window.area.top, w.window.area.width, w.window.area.height)
   canvas:attrColor(0, 0, 0, 0)
   canvas:clear()

   for i = 1, #w.intersections do
      local intersec = w.intersections[i]
      if (next(intersec)) then
         canvas:compose(self.stack[i].window.area.left, self.stack[i].window.area.top, self.stack[i].window.content)
      end
   end
   canvas:attrClip(clipX, clipY, clipW, clipH)
   w.window = nil

   window.parent = self

   clipX, clipY, clipW, clipH = canvas:attrClip()
   canvas:attrClip(window.area.left, window.area.top, window.area.width, window.area.height)
   canvas:compose(window.area.left, window.area.top, window.content)
   canvas:attrClip(clipX, clipY, clipW, clipH)

   local intersectList = {}
   for i = 1, #self.stack do
      local w = self.stack[i].window
      local interRect = hasIntersection(window, w)
      table.insert(intersectList, interRect)
   end

   self.stack[#self.stack + 1] = {window = window, intersections = intersectList}

   canvas:flush()
   collectgarbage()
end

function StackWindow:clear()
   self:pop(#self.stack)
end

return StackWindow
